package com.seleniti.enpareja.web.desktop.server.model.integration.service.impl.appengine;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import org.apache.log4j.Logger;
import org.ioc.commons.japtsy.server.model.biz.JAPTSYService_JDOImpl;
import org.ioc.commons.utils.Format;
import org.ioc.commons.utils.jdo.JdoQueryHelper;
import org.joda.time.DateTime;
import org.joda.time.DateTimeComparator;

import com.seleniti.enpareja.controller.common.domain.LoggedUserInfo;
import com.seleniti.enpareja.controller.common.exception.EnParejaException;
import com.seleniti.enpareja.controller.model.integration.database.domain.Couple;
import com.seleniti.enpareja.controller.model.integration.database.domain.Food;

public class GAEMealService extends GAEService {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(GAEMealService.class);

	public GAEMealService() {
		logger.info("GAE Couple service instance");
	}

	public Food find(String id) {
		return pm.getObjectById(Food.class, id);
	}

	public void delete(Food ht) throws EnParejaException {
		pm.deletePersistent(ht);
	}

	public void deleteAll(Set<Food> ht) throws EnParejaException {
		pm.deletePersistentAll(ht);
	}

	public void createOrReplace(Date date, String lunch, String dinner) {
		JdoQueryHelper qh = JdoQueryHelper.newQuery(pm, Food.class);

		logger.info(Format.substitute("Creating or replace meal for date {0}", date));

		Couple couple = addLoggedUserCoupleFilter(qh);

		qh.andParams("date==%s", date);
		qh.setUnique(true);

		Food found = (Food) qh.execute();

		if (found == null) {
			found = new Food();
			found.setCouple(couple);
			found.setDate(date);
		}

		found.setLunch(lunch);
		found.setDinner(dinner);

		pm.makePersistent(found);
	}

	public List<Food> getList(Date from, Date to, boolean createIfMissing) {
		List<Food> list = new ArrayList<Food>();

		if (!createIfMissing) {
			JdoQueryHelper qh = JdoQueryHelper.newQuery(pm, Food.class);
			addLoggedUserCoupleFilter(qh);

			qh.andParams("date >= %s && date <= %s", from, to);
			qh.setOrdering("date asc");

			@SuppressWarnings("unchecked")
			List<Food> found = (List<Food>) qh.execute();

			list.addAll(found);

		} else {
			DateTimeComparator dtc = DateTimeComparator.getDateOnlyInstance();

			logger.info(Format.substitute("From: {0} To {1}", from, to));

			DateTime current = new DateTime(from);
			while (dtc.compare(current, to) <= 0) {

				Date date = current.toDate();
				JdoQueryHelper qh = JdoQueryHelper.newQuery(pm, Food.class);
				Couple couple = addLoggedUserCoupleFilter(qh);

				qh.andParams("date == %s", date);
				qh.setUnique(true);

				Food found = (Food) qh.execute();

				logger.info(Format.substitute("Exists for? {0} {1}", date, found != null));

				if (found == null) {
					found = new Food();
					found.setCouple(couple);
					found.setDate(date);
				}

				list.add(found);

				current = current.plusDays(1);

			}
		}

		logger.debug(Format.substitute("Dates got: {0}",
				Format.collectionToString(list, new Format.StringFormatter<Food>() {

					@Override
					public String asString(Food obj) {
						return obj != null ? String.valueOf(obj.getDate()) : null;
					}
				})));

		logger.debug(Format.substitute("Dates json formated: {0}",
				Format.collectionToString(list, new Format.StringFormatter<Food>() {

					@Override
					public String asString(Food obj) {
						return obj != null ? new JAPTSYService_JDOImpl().formatDateTime(obj.getDate()) : null;
					}
				})));

		return list;
	}

	public void switchMeals(Food meal1, boolean switchDinnerMeal1, Food meal2, boolean switchDinnerMeal2)
			throws EnParejaException {
		String text1 = !switchDinnerMeal1 ? meal1.getLunch() : meal1.getDinner();
		String text2 = !switchDinnerMeal2 ? meal2.getLunch() : meal2.getDinner();

		LoggedUserInfo loggedUserInfo = assertLoggedIn("Switch meals");
		String coupleId = loggedUserInfo.getCoupleId();
		Couple couple = coupleId != null ? pm.getObjectById(Couple.class, coupleId) : null;

		Food other1 = getByDate(meal1.getDate());
		Food other2 = getByDate(meal2.getDate());

		if (other1 != null && !Objects.equals(other1.getFoodId(), meal1.getFoodId())) {
			pm.deletePersistent(other1);
		}

		if (other2 != null && !Objects.equals(other2.getFoodId(), meal2.getFoodId())) {
			pm.deletePersistent(other2);
		}

		if (!switchDinnerMeal1) {
			meal1.setLunch(text2);
		} else {
			meal1.setDinner(text2);
		}

		if (!switchDinnerMeal2) {
			meal2.setLunch(text1);
		} else {
			meal2.setDinner(text1);
		}

		if (meal1.getFoodId() == null) {
			meal1.setCouple(couple);
			pm.makePersistent(meal1);
		}
		if (meal2.getFoodId() == null) {
			meal2.setCouple(couple);
			pm.makePersistent(meal2);
		}
	}

	private Food getByDate(Date date) {
		JdoQueryHelper qh = JdoQueryHelper.newQuery(pm, Food.class);
		addLoggedUserCoupleFilter(qh);

		qh.andParams("date == %s", new Date(date.getTime()));
		qh.setUnique(true);

		Food found = (Food) qh.execute();

		return found;
	}
}
